package com.xt.base.environment;

import java.io.Serializable;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

import com.xt.base.dao.hibernate.BaseDaoHibernate;
import com.xt.base.exception.SystemError;

/**
 * 环境 <br>
 * 
 * <p>
 * <a href="Environment.java.html"><i>查看源文件</i></a>
 * </p>
 * 
 * @author 杨洪波
 * @version $Revision: $<br>
 *          $Id: $
 */
public final class Environment<T> implements Serializable {

	private static final long serialVersionUID = 8952973042865659783L;

	/**
	 * 供实例化内部类使用的钩子
	 */
	public static Environment hook = new Environment();

	/**
	 * 值提供器接口
	 */
	public interface ValueProvider {

		/**
		 * 提供经过包装的值
		 * 
		 * @param 参数数组
		 * @return 经过包装的值
		 */
		abstract public <V> V getValue(Object[] args);
	}

	/**
	 * 空环境提供器。供某些不需要提供环境的方法使用的桩
	 */
	public class NullProvider extends EnvironmentProvider.Default {

		private static final long serialVersionUID = -885994798934037960L;

	}

	/**
	 * HttpServletRequest和BaseDaoHibernate环境提供器
	 */
	public class RequestAndDaoProvider extends EnvironmentProvider.Default {

		private static final long serialVersionUID = 2695139283170519388L;

		public RequestAndDaoProvider(HttpServletRequest request,
				BaseDaoHibernate dao) {
			envs = new Environment[] {
					new Environment<HttpServletRequest>("request", request,
							new ValueProvider() {
								@SuppressWarnings("unchecked")
								public <V> V getValue(Object[] args) {
									String value = null;
									if (args != null && args.length == 1
											&& String.class.isInstance(args[0])) {
										HttpServletRequest req = get(HttpServletRequest.class).environment;
										value = req
												.getParameter((String) args[0]);
										if (StringUtils.isEmpty(value))
											value = (String) req
													.getAttribute((String) args[0]);
										return (V) value;
									} else
										throw new IllegalArgumentException();
								}
							}),
					new Environment<BaseDaoHibernate>("dao", dao,
							new ValueProvider() {
								@SuppressWarnings("unchecked")
								public <V> V getValue(Object[] args) {
									if (args != null && args.length == 2
											&& Class.class.isInstance(args[0])
											&& String.class.isInstance(args[1])) {
										BaseDaoHibernate dao = get(BaseDaoHibernate.class).environment;
										return (V) dao.getObject(
												(Class) args[0],
												(String) args[1]);
									} else
										throw new IllegalArgumentException();
								}

							}) 
				};
		}
	}

	/** 名称 */
	public final String name;

	/** 环境对象 */
	public final T environment;

	/** 环境类型 */
	public final Class type;

	/** 值提供器 */
	private final ValueProvider valueProvider;

	public Environment() {
		name = "hook";
		environment = null;
		type = null;
		valueProvider = null;
	}

	public Environment(String name, T environment) {
		this.name = name;
		this.environment = environment;
		this.type = environment.getClass();
		this.valueProvider = null;
	}

	public Environment(String name, T environment, ValueProvider valueProvider) {
		this.name = name;
		this.environment = environment;
		this.type = environment.getClass();
		this.valueProvider = valueProvider;
	}

	/**
	 * 提供经过包装的值
	 * 
	 * @param 参数数组
	 * @return 经过包装的值
	 */
	public <V> V get(Object... args) {
		if (valueProvider != null)
			return valueProvider.getValue(args);
		throw new SystemError(this, args);
	}
}
